from datetime import timedelta
from typing import Dict, Any, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from pydantic import BaseModel, EmailStr, validator
from app.database.connection import get_db
from app.services.auth_service import auth_service
from app.models.user import User
import logging

# 配置日志
logger = logging.getLogger(__name__)

# 创建路由器
router = APIRouter(prefix="/auth", tags=["认证"])

# HTTP Bearer 认证
security = HTTPBearer()

# Pydantic 模型
class UserLogin(BaseModel):
    """用户登录模型"""
    username: str
    password: str
    
    @validator('username')
    def username_must_not_be_empty(cls, v):
        if not v or not v.strip():
            raise ValueError('用户名不能为空')
        return v.strip()
    
    @validator('password')
    def password_must_not_be_empty(cls, v):
        if not v or len(v) < 6:
            raise ValueError('密码长度不能少于6位')
        return v

class UserRegister(BaseModel):
    """用户注册模型"""
    username: str
    email: EmailStr
    password: str
    confirm_password: str
    
    @validator('username')
    def username_validation(cls, v):
        if not v or not v.strip():
            raise ValueError('用户名不能为空')
        if len(v.strip()) < 3:
            raise ValueError('用户名长度不能少于3位')
        if len(v.strip()) > 20:
            raise ValueError('用户名长度不能超过20位')
        return v.strip()
    
    @validator('password')
    def password_validation(cls, v):
        if not v or len(v) < 6:
            raise ValueError('密码长度不能少于6位')
        if len(v) > 50:
            raise ValueError('密码长度不能超过50位')
        return v
    
    @validator('confirm_password')
    def passwords_match(cls, v, values):
        if 'password' in values and v != values['password']:
            raise ValueError('两次输入的密码不一致')
        return v

class UserProfile(BaseModel):
    """用户资料更新模型"""
    nickname: str = None
    bio: str = None
    avatar_url: str = None
    preferences: Dict[str, Any] = None

class UserProfileData(BaseModel):
    """用户画像数据模型"""
    age_group: str = None
    gender: str = None
    location: str = None
    favorite_genres: list = None
    emotional_preferences: Dict[str, Any] = None
    favorite_actors: list = None
    favorite_directors: list = None
    mood_history: list = None
    
    @validator('age_group')
    def validate_age_group(cls, v):
        if v and v not in ['teenager', 'young_adult', 'middle_aged', 'senior']:
            raise ValueError('年龄段选项无效')
        return v
    
    @validator('gender')
    def validate_gender(cls, v):
        if v and v not in ['male', 'female', 'other', 'prefer_not_to_say']:
            raise ValueError('性别选项无效')
        return v

class PasswordChange(BaseModel):
    """密码修改模型"""
    old_password: str
    new_password: str
    confirm_password: str
    
    @validator('new_password')
    def password_validation(cls, v):
        if not v or len(v) < 6:
            raise ValueError('新密码长度不能少于6位')
        if len(v) > 50:
            raise ValueError('新密码长度不能超过50位')
        return v
    
    @validator('confirm_password')
    def passwords_match(cls, v, values):
        if 'new_password' in values and v != values['new_password']:
            raise ValueError('两次输入的新密码不一致')
        return v

class TokenResponse(BaseModel):
    """令牌响应模型"""
    access_token: str
    token_type: str
    expires_in: int
    user: Dict[str, Any]

class UserResponse(BaseModel):
    """用户响应模型"""
    id: int
    username: str
    email: str
    nickname: str
    bio: Optional[str] = None
    avatar_url: Optional[str] = None
    is_active: bool
    is_verified: bool
    is_premium: bool
    created_at: str
    last_login_at: Optional[str] = None

# 依赖函数
async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db)) -> User:
    """获取当前用户
    Args:
        credentials: HTTP认证凭据
        db: 数据库会话
    Returns:
        User: 当前用户对象
    Raises:
        HTTPException: 认证失败时抛出异常
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="认证失败",
        headers={"WWW-Authenticate": "Bearer"},
    )
    
    try:
        # 验证令牌
        payload = auth_service.verify_token(credentials.credentials)
        if payload is None:
            raise credentials_exception
        
        # 获取用户ID
        user_id: int = payload.get("sub")
        if user_id is None:
            raise credentials_exception
        
        # 获取用户
        user = auth_service.get_user_by_id(db, user_id=int(user_id))
        if user is None:
            raise credentials_exception
        
        return user
        
    except Exception as e:
        logger.error(f"获取当前用户异常: {e}")
        raise credentials_exception

# API 路由
@router.post("/login", response_model=TokenResponse, summary="用户登录")
async def login(user_data: UserLogin, db: Session = Depends(get_db)):
    """用户登录
    
    Args:
        user_data: 登录数据
        db: 数据库会话
        
    Returns:
        TokenResponse: 登录成功返回令牌信息
        
    Raises:
        HTTPException: 登录失败时抛出异常
    """
    try:
        # 用户认证
        user = auth_service.authenticate_user(db, user_data.username, user_data.password)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="用户名或密码错误"
            )
        
        # 创建访问令牌
        access_token_expires = timedelta(minutes=auth_service.access_token_expire_minutes)
        access_token = auth_service.create_access_token(
            data={"sub": str(user.id)},
            expires_delta=access_token_expires
        )
        
        logger.info(f"用户登录成功: {user.username}")
        
        return {
            "access_token": access_token,
            "token_type": "bearer",
            "expires_in": auth_service.access_token_expire_minutes * 60,
            "user": user.to_dict()
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"登录异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="登录失败，请稍后重试"
        )

@router.post("/register", summary="用户注册")
async def register(user_data: UserRegister, db: Session = Depends(get_db)):
    """用户注册
    
    Args:
        user_data: 注册数据
        db: 数据库会话
        
    Returns:
        Dict: 注册结果
        
    Raises:
        HTTPException: 注册失败时抛出异常
    """
    try:
        # 用户注册
        result = auth_service.register_user(
            db=db,
            username=user_data.username,
            email=user_data.email,
            password=user_data.password
        )
        
        if not result["success"]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=result["message"]
            )
        
        logger.info(f"用户注册成功: {user_data.username}")
        
        return {
            "success": True,
            "message": "注册成功，请登录"
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"注册异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="注册失败，请稍后重试"
        )

@router.get("/me", response_model=UserResponse, summary="获取当前用户信息")
async def get_current_user_info(current_user: User = Depends(get_current_user)):
    """获取当前用户信息
    
    Args:
        current_user: 当前用户
        
    Returns:
        UserResponse: 用户信息
    """
    try:
        user_dict = current_user.to_dict()
        return UserResponse(
            id=user_dict["id"],
            username=user_dict["username"],
            email=user_dict["email"],
            nickname=user_dict["nickname"],
            bio=user_dict.get("bio"),
            avatar_url=user_dict.get("avatar_url"),
            is_active=user_dict["is_active"],
            is_verified=user_dict["is_verified"],
            is_premium=user_dict["is_premium"],
            created_at=user_dict["created_at"],
            last_login_at=user_dict.get("last_login_at")
        )
        
    except Exception as e:
        logger.error(f"获取用户信息异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取用户信息失败"
        )

@router.put("/profile", summary="更新用户资料")
async def update_profile(
    profile_data: UserProfile,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """更新用户资料
    
    Args:
        profile_data: 资料数据
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        Dict: 更新结果
        
    Raises:
        HTTPException: 更新失败时抛出异常
    """
    try:
        # 过滤空值
        update_data = {k: v for k, v in profile_data.dict().items() if v is not None}
        
        if not update_data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="没有需要更新的数据"
            )
        
        # 更新用户资料
        result = auth_service.update_user_profile(db, current_user.id, update_data)
        
        if not result["success"]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=result["message"]
            )
        
        logger.info(f"用户资料更新成功: {current_user.username}")
        
        return result
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新用户资料异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新失败，请稍后重试"
        )

@router.put("/password", summary="修改密码")
async def change_password(
    password_data: PasswordChange,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """修改密码
    
    Args:
        password_data: 密码数据
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        Dict: 修改结果
        
    Raises:
        HTTPException: 修改失败时抛出异常
    """
    try:
        # 修改密码
        result = auth_service.change_password(
            db=db,
            user_id=current_user.id,
            old_password=password_data.old_password,
            new_password=password_data.new_password
        )
        
        if not result["success"]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=result["message"]
            )
        
        logger.info(f"用户密码修改成功: {current_user.username}")
        
        return result
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"修改密码异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="修改失败，请稍后重试"
        )

@router.post("/verify-token", summary="验证令牌")
async def verify_token(current_user: User = Depends(get_current_user)):
    """验证令牌有效性
    
    Args:
        current_user: 当前用户
        
    Returns:
        Dict: 验证结果
    """
    return {
        "valid": True,
        "user": current_user.to_dict()
    }

@router.post("/logout", summary="用户登出")
async def logout(current_user: User = Depends(get_current_user)):
    """用户登出
    
    Args:
        current_user: 当前用户
        
    Returns:
        Dict: 登出结果
    """
    logger.info(f"用户登出: {current_user.username}")
    
    return {
        "success": True,
        "message": "登出成功"
    }

@router.get("/profile-data", summary="获取用户画像")
async def get_user_profile_data(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取用户画像数据
    
    Args:
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        Dict: 用户画像数据
    """
    try:
        # 获取用户画像
        result = auth_service.get_user_profile_data(db, current_user.id)
        
        if result["success"]:
            return result["data"]
        else:
            # 返回默认值
            return {
                "age_group": None,
                "gender": None,
                "location": None,
                "favorite_genres": [],
                "emotional_preferences": [],
                "favorite_actors": [],
                "favorite_directors": [],
                "mood_history": []
            }
            
    except Exception as e:
        logger.error(f"获取用户画像异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取用户画像失败"
        )

@router.put("/profile-data", summary="更新用户画像")
async def update_user_profile_data(
    profile_data: UserProfileData,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """更新用户画像数据
    
    Args:
        profile_data: 画像数据
        current_user: 当前用户
        db: 数据库会话
        
    Returns:
        Dict: 更新结果
    """
    try:
        # 过滤空值
        update_data = {k: v for k, v in profile_data.dict().items() if v is not None}
        
        if not update_data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="没有需要更新的数据"
            )
        
        # 更新用户画像
        result = auth_service.update_user_profile_data(db, current_user.id, update_data)
        
        if not result["success"]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=result["message"]
            )
        
        logger.info(f"用户画像更新成功: {current_user.username}")
        
        # 直接返回更新后的数据
        return result["data"]
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新用户画像异常: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新失败，请稍后重试"
        )